package util

import (
	"regexp"
	"strconv"
	"strings"
)

type Asserts struct {
	Assert
	Children []Assert
}

type Assert struct {
	HttpCode     int    `json:"http_code"`
	Name         string `json:"name"`
	Required     bool   `json:"required"`
	ValidateType bool   `json:"validate_type"`
	FieldType    string `json:"field_type"`
	// 校验模式 nocheck  value  length  reg
	Mode string `json:"mode"`
	// 校验运算方式  >、>=、!= ...
	Operator     string      `json:"operator"`
	ExpectResult interface{} `json:"expect_result"`
}

func AssertJsonIntValue(val, expectValue int, operator string) bool {
	switch operator {
	case "value=":
		if val != expectValue {
			return false
		}
	case "value!=":
		if val == expectValue {
			return false
		}
	case "value>":
		if val <= expectValue {
			return false
		}
	case "value>=":
		if val < expectValue {
			return false
		}
	case "value<":
		if val >= expectValue {
			return false
		}
	case "value<=":
		if val > expectValue {
			return false
		}
	default:
		return false
	}

	return true
}

func AssertJsonStringValue(val, expectValue string, operator string) bool {
	switch operator {
	case "value=":
		if val != expectValue {
			return false
		}
	case "value!=":
		if val == expectValue {
			return false
		}
	case "value>":
		if val <= expectValue {
			return false
		}
	case "value>=":
		if val < expectValue {
			return false
		}
	case "value<":
		if val >= expectValue {
			return false
		}
	case "value<=":
		if val > expectValue {
			return false
		}
	case "contains":
		return strings.Contains(val, expectValue)
	case "!contains":
		return !strings.Contains(val, expectValue)
	case "length=":
		length, err := strconv.Atoi(expectValue)
		if err != nil {
			return false
		}
		if len([]rune(val)) != length {
			return false
		}
	case "length!=":
		length, err := strconv.Atoi(expectValue)
		if err != nil {
			return false
		}
		if len([]rune(val)) == length {
			return false
		}
	case "length>":
		length, err := strconv.Atoi(expectValue)
		if err != nil {
			return false
		}
		if len([]rune(val)) <= length {
			return false
		}
	case "length<":
		length, err := strconv.Atoi(expectValue)
		if err != nil {
			return false
		}
		if len([]rune(val)) >= length {
			return false
		}
	case "reg":
		if !regexp.MustCompile(expectValue).MatchString(val) {
			return false
		}
	default:
		return false
	}

	return true
}

func AssertJsonBoolValue(val, expectValue bool, operator string) bool {
	switch operator {
	case "value=":
		if val != expectValue {
			return false
		}
	case "value!=":
		if val == expectValue {
			return false
		}

	default:
		return false
	}

	return true
}

func AssertJsonFloat64Value(val, expectValue float64, operator string) bool {
	switch operator {
	case "value=":
		if val != expectValue {
			return false
		}
	case "value!=":
		if val == expectValue {
			return false
		}
	case "value>":
		if val <= expectValue {
			return false
		}
	case "value>=":
		if val < expectValue {
			return false
		}
	case "value<":
		if val >= expectValue {
			return false
		}
	case "value<=":
		if val > expectValue {
			return false
		}
	default:
		return false
	}

	return true
}

func AssertJsonArray(val []interface{}, expectValue int, operator string) bool {
	switch operator {
	case "length=":
		return len(val) == expectValue
	case "length!=":
		return len(val) != expectValue
	case "length<":
		return len(val) < expectValue
	case "length<=":
		return len(val) <= expectValue
	case "length>":
		return len(val) > expectValue
	case "length>=":
		return len(val) >= expectValue
	default:
		return true
	}
}

func AssertXmlArray(curLen, expectValue int, operator string) bool {
	switch operator {
	case "length=":
		return curLen == expectValue
	case "length!=":
		return curLen != expectValue
	case "length<":
		return curLen < expectValue
	case "length<=":
		return curLen <= expectValue
	case "length>":
		return curLen > expectValue
	case "length>=":
		return curLen >= expectValue
	default:
		return true
	}
}
